import type { Callback, ValidatorFn } from "@/types/form";

const regMap = {
  // 中英文和数字
  noSpecialLetter: /^[\u4e00-\u9fa5a-zA-Z0-9]+$/,
  limitSpecialLetter: /^[\u4e00-\u9fa5a-zA-Z0-9\-_()（）]+$/,
  // 英文及英文标点
  letterNumAndPoint: /^[a-zA-Z0-9]+((\.|:)[a-zA-Z0-9]+)*$/,
  // 英文及数字
  letterNum: /^[a-zA-Z0-9]+$/,
  // 正整数
  num: /^[1-9][0-9]*$/,
  // 最多两位小数
  float: /^(([0])|([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/,
  // 路径
  path: /^(\/[a-zA-Z0-9]+)+$/,
  // 手机号
  phone: /^1[3456789]\d{9}$/,
  tel: /^((0\d{2,3}-\d{7,8})|(1[3456789]\d{9}))$/,
  url: /^(https?):\/\/[\w-]+(\.[\w-]+)+([\w\-.,@?^=%&:/~+#]*[\w\-@?^=%&/~+#])?$/,
  email: /^\w+((.\w+)|(-\w+))@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+).[A-Za-z0-9]+$/,
  // 密码校验, 8-12位密码，必须包含英文, 数字和特殊字符
  password: /^(?=.*\d)(?=.*[A-Za-z])(?=.*[.,;'"*+!?^_${}()|[\]\\=@#\-~<>/%&`:])[\x21-\x7e]{8,12}$/,
  idNo: /(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)/,
  // 中英文加.
  version: /^[a-zA-z0-9.]+$/
};

/**
 * 正则校验
 * @param reg 正则表达式
 * @param msg 提示信息
 */
function validateReg(reg: RegExp, msg: string) {
  return async function (rule: unknown, value: string) {
    return !value || reg.test(value) ? Promise.resolve() : Promise.reject(msg);
  };
}

/**
 * 字符长度校验
 * @param min 最小值
 * @param max 最大值
 * @param message 提示信息
 */
export function validLength(min: number, max: number, message: string) {
  if (!message) {
    message = `长度在${min}到${max}个字符`;
  }
  return { min, max, message, trigger: 'blur' };
}

/**
 * 最大值校验
 * @param max 最大值
 * @param message 提示信息
 */
export function validMaxLength(max: number, message: string) {
  if (!message) {
    message = `长度超过${max}个字符`;
  }
  return { max, message, trigger: 'blur' };
}

/**
 * 通用正则校验方式
 * @param key regMap中已定义的正则字段
 * @param msg 提示信息
 * @param trigger 触发方式
 * @returns 校验规则
 */
export function validReg(key: keyof typeof regMap | 'required', msg: string, trigger = 'blur') {
  if (key === 'required') {
    return { required: true, message: msg, trigger };
  }
  return { validator: validateReg(regMap[key], msg), trigger };
}

/**
 * 验证二代身份证校验位有效性
 * @param {String} idNo 身份证号
 * @return Boolean
 */
export function validateIdNoParity(idNo: string) {
  const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
  if (idNo.length === 18) {
    const code = idNo.substring(17);
    let sum = 0;
    for (let i = 0; i < 17; i++) {
      sum = sum + Number(idNo[i]) * factor[i];
    }
    return parity[sum % 11].toString() === code.toUpperCase();
  }
  return true;
}

/**
 * 自定义校验规则
 * @param func 自定义校验函数
 * @param message 提示信息
 * @param trigger 触发方式
 */
export function validFunc(func: ValidatorFn, message: string, trigger = 'blur') {
  return {
    validator: (rule: unknown, value: string, cb: Callback) => {
      if (func(value)) {
        cb();
      } else {
        cb(new Error(message));
      }
    },
    trigger
  };
}
